package com.koron.car.web.authorized.service.impl;

import com.alibaba.fastjson.JSON;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.workflow.RedirectQuery;
import com.koron.car.config.Constants;
import com.koron.car.web.authorized.bean.entity.CarDelimit;
import com.koron.car.web.authorized.bean.entity.DelimitApply;
import com.koron.car.web.authorized.bean.entity.DelimitChange;
import com.koron.car.web.authorized.bean.query.DelimitApplyQuery;
import com.koron.car.web.authorized.bean.vo.DelimitApplyVO;
import com.koron.car.web.authorized.bean.vo.OperateControlVO;
import com.koron.car.web.authorized.mapper.CarDelimitMapper;
import com.koron.car.web.authorized.mapper.DelimitApplyMapper;
import com.koron.car.web.authorized.mapper.OperateControlMapper;
import com.koron.car.web.authorized.service.CarDelimitService;
import com.koron.car.web.authorized.service.DelimitApplyService;
import com.koron.car.web.authorized.service.DelimitChangeService;
import com.koron.car.web.authorized.service.OperateControlService;
import com.koron.car.web.carledger.mapper.CarMapper;
import com.koron.car.web.common.CommonUtils;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * (DelimitApply)表服务实现类
 *
 * @author twcao
 * @since 2022-03-31 11:24:56
 */
@Slf4j
@Service
public class DelimitApplyServiceImpl implements DelimitApplyService {

    @Autowired
    private DelimitChangeService delimitChangeService;

    @Autowired
    private CarDelimitService delimitService;

    @Autowired
    private OperateControlService ocService;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("queryById")
    public DelimitApplyVO queryById(SessionFactory factory, String id) {
        DelimitApplyMapper mapper = factory.getMapper(DelimitApplyMapper.class);
        DelimitApplyVO delimit = mapper.queryById(id);
        return delimit;
    }

    /**
     * 查询多条数据
     * @param query
     * @return 对象列表
     */
    @Override
    @TaskAnnotation("queryList")
    public List<DelimitApply> queryList(SessionFactory factory, DelimitApplyQuery query) {
        DelimitApplyMapper mapper = factory.getMapper(DelimitApplyMapper.class);
        return mapper.queryList(query);
    }

    @Override
    @TaskAnnotation("saveOrUpdate")
    public DelimitApplyVO saveOrUpdate(SessionFactory factory, DelimitApplyVO apply) {
        Assert.notNull(apply, "申请信息不能为空");
        if(StringUtils.isBlank(apply.getId())) {
            insert(factory, apply);
        } else {
            update(factory, apply);
        }
        return queryById(factory, apply.getId());
    }

    /**
     * 新增数据
     * @param apply 实例对象
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("insert")
    public DelimitApply insert(SessionFactory factory, DelimitApply apply) {
        DelimitApplyMapper mapper = factory.getMapper(DelimitApplyMapper.class);
        // 1、只能有一个申请单
        //List<DelimitApply> delimitApplies = mapper.queryList(new DelimitApplyQuery().setStates(Arrays.asList(Constants.DelimitApplyState.DRAFT, Constants.DelimitApplyState.WAIT_REVIEW)));
        //Assert.isTrue(CollectionUtils.isEmpty(delimitApplies), "有未完成的定编申请");
        // 2、保存申请
        EamUser eamUser = ThreadLocalContext.get();
        CommonUtils.update(apply, eamUser);
        apply.setDeptId(eamUser.getOrgId());
        apply.setMark(eamUser.getCurrDs());
        apply.setState(Constants.DelimitApplyState.DRAFT);
        apply.setCode(CommonUtils.getCodeNo(Constants.CAR_DELIMIT_CODE, 3));
        apply.setId(CodeTools.getCode32());
        mapper.insert(apply);
        // 3、将上次申请结束后的编号，作为这次的初始值
        CarDelimitMapper delimitMapper = factory.getMapper(CarDelimitMapper.class);
        List<CarDelimit> carDelimits = delimitMapper.queryList(null);
        if(CollectionUtils.isNotEmpty(carDelimits)) {
            List<DelimitChange> delimits = carDelimits.stream().map(row -> {
                DelimitChange change = new DelimitChange();
                change.setApplyId(apply.getId());
                change.setDelimitNum(row.getPrepareNumber());
                change.setDelimitType(row.getPrepareType());
                return change;
            }).collect(Collectors.toList());
            delimitChangeService.insertBatch(factory, delimits);
        }
        OperateControlVO oc = ocService.queryByMark(factory);
        if (com.koron.common.core.util.StringUtils.isNotNull(oc)){
            oc.setApplyId(apply.getId());
            ocService.insert(factory, oc);
        }
        return apply;
    }

    /**
     * 修改数据
     * @param apply 实例对象
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("update")
    public DelimitApply update(SessionFactory factory, DelimitApply apply) {
        DelimitApplyMapper mapper = factory.getMapper(DelimitApplyMapper.class);
        EamUser eamUser = ThreadLocalContext.get();
        CommonUtils.update(apply, eamUser);
        apply.setMark(eamUser.getCurrDs());
        mapper.update(apply);
        return this.queryById(factory, apply.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    @TaskAnnotation("deleteById")
    public boolean deleteById(SessionFactory factory, String id) {
        DelimitApplyMapper mapper = factory.getMapper(DelimitApplyMapper.class);
        delimitChangeService.deleteByApplyId(factory, id);
        return mapper.deleteById(id) > 0;
    }

    @Override
    @TaskAnnotation("workflowUpdate")
    public Boolean workflowUpdate(SessionFactory factory, RedirectQuery redirectQuery) {
        Integer operation = redirectQuery.getOperation();
        DelimitApplyVO vo = JSON.parseObject(redirectQuery.getFormVariables(), DelimitApplyVO.class);
        switch (operation) {
            case 256: // 撤回
            case 1: // 驳回
                // 驳回的节点编号
                vo.setState(Constants.DelimitApplyState.DRAFT);
                break;
            case 32: // 同意
                vo.setState(Constants.DelimitApplyState.WAIT_REVIEW);
                break;
        }
        saveOrUpdate(factory, vo);
        return true;
    }

    @Override
    @TaskAnnotation("auditFinish")
    public DelimitApplyVO auditFinish(SessionFactory factory, DelimitApplyVO detail) {
        DelimitApplyMapper mapper = factory.getMapper(DelimitApplyMapper.class);
        detail.setState(Constants.DelimitApplyState.FINISH);
        // 1、更新申请的状态为已完成
        DelimitApply apply = new DelimitApply();
        apply.setId(detail.getId());
        apply.setState(detail.getState());
        mapper.update(apply);
        // 2、查出所有的定编号（存放）
        List<CarDelimit> carDelimits = delimitService.queryList(factory, null);
        Map<String, CarDelimit> oldPrepareNumberMap = carDelimits.stream().collect(Collectors.toMap(CarDelimit::getPrepareNumber, item -> item));
        // 3、清空定编表，后面新增最终确定的定编号
        delimitService.clean(factory);
        List<DelimitChange> changes = delimitChangeService.queryByApplyId(factory, detail.getId());
        Assert.notEmpty(changes,"变更列表不能为空");
        // 4、将变更列表转换为定编号列表，以最后一次变更为主
        List<CarDelimit> delimits = changes.stream().map(row -> {
            if(oldPrepareNumberMap.containsKey(row.getDelimitNum())) {
                // 如果是已经有的编号，则用之前的, 将id设置为空，后面需重新排序
                CarDelimit carDelimit = oldPrepareNumberMap.get(row.getDelimitNum());
                return carDelimit;
            }
            // 如果没有，则新建一个定编号，并设置为未定编
            return new CarDelimit(row.getDelimitType(), row.getDelimitNum(), Constants.DelimitState.UNBOUNDED);
        }).sorted(Comparator.comparing(CarDelimit::getPrepareNumber)).collect(Collectors.toList());
        delimitService.saveOrUpdate(factory, delimits);
        // 5、修改编制概况
        OperateControlMapper ocMapper = factory.getMapper(OperateControlMapper.class);
        OperateControlVO oldOc = ocMapper.queryByMark(factory.getDbEnv());
        OperateControlVO oc = new OperateControlVO();
        // 定编经营管理用车数量
        int delimitManagerNum = delimits.stream().filter(row -> StringUtils.equals(row.getPrepareType(), Constants.PrepareType.DELIMIT_MANAGER)).collect(Collectors.toList()).size();
        // 定编业务保障用车数量
        int delimitSecurityNum = delimits.stream().filter(row -> StringUtils.equals(row.getPrepareType(), Constants.PrepareType.DELIMIT_SECURITY)).collect(Collectors.toList()).size();
        oc.setDelimitManagerNum(delimitManagerNum);
        oc.setDelimitSecurityNum(delimitSecurityNum);
        oc.setDelimitEffectTime(detail.getEffectTime());
        oc.setId(oldOc.getId());
        ocMapper.update(oc);
        // 6、将不在最新编制内的车辆的编号置空
        List<String> newestDelimit = delimits.stream().map(CarDelimit::getPrepareNumber).collect(Collectors.toList());
        // 旧的编号
        List<String> oldDelimit = carDelimits.stream().map(CarDelimit::getPrepareNumber).collect(Collectors.toList());
        // 待解绑的编号
        Collection<String> unBound = CollectionUtils.subtract(oldDelimit, newestDelimit);
        if(CollectionUtils.isNotEmpty(unBound)) {
            CarMapper carMapper = factory.getMapper(CarMapper.class);
            //carMapper.unboundDelimitNum(Constants.PrepareType.NOLIMIT, new ArrayList<>(unBound));
            carMapper.unboundDelimitNum(null, new ArrayList<>(unBound));
        }
        return detail;
    }
}
